package org.liujing.jeditplugin.ui;

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.util.*;
import java.util.logging.*;


public class FitWidthTable extends JTable
{
	static Logger log = Logger.getLogger(FitWidthTable.class.getName());
	
	protected boolean enablePack = true;

	public FitWidthTable()
	{
		super();
		init();
	}
	public FitWidthTable(TableModel dm)
	{
		super(dm);
		init();
	}
	/**
	overwrite it
	*/
	protected void init()
	{
		setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		//setDefaultRenderer(Object.class, new FitWidthTableRenderer());
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		//setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS);
		setRowHeight(20);
		//setPreferredScrollableViewportSize(new Dimension(1000,600));
		
		//log.fine("before init size");
		resizeTable(0, Integer.MAX_VALUE, TableModelEvent.ALL_COLUMNS);
		//log.fine("after init size");
	}
	/**
		set whether you want to pack the table when the table is filled with data, or data is updated
	*/
	//public void enableAutoPack(boolean b)
	//{
	//	enablePack=b;
	//	if(b)
	//		resizeTable();
	//}
	
	public int getPreferredRowHeight(int firstColumn, int lastColumn, int rowIndex) {
	    // Get the current default height for all rows
	    int height = getRowHeight();
	
	    // Determine highest cell in the row
	    for (int c = firstColumn; c <= lastColumn; c++) {
	        TableCellRenderer renderer = getCellRenderer(rowIndex, c);
	        Component comp = prepareRenderer(renderer, rowIndex, c);
	        int h = comp.getPreferredSize().height + (getRowMargin()<<1);
	        height = Math.max(height, h);
	        if(isCellEditable(rowIndex, c)){
	        	TableCellEditor editor = getCellEditor(rowIndex, c);
	        	comp = prepareEditor(editor, rowIndex, c);
	        	height = Math.max(height, comp.getPreferredSize().height);
	        }
	    }
	    return height;
	}
    

	public int getPreferredColumnWidth(int firstRow, int lastRow, int colomnIdx)
	{
		int w = getColumnModel().getColumn(colomnIdx).getPreferredWidth();
		//log.fine("get preferred width: " + w);
		Component hcomp = null;
		TableCellRenderer renderer = null;
		if(firstRow == -1){
			TableCellRenderer tHrenderer=getTableHeader().getDefaultRenderer();
			hcomp = tHrenderer.getTableCellRendererComponent(this, getColumnModel().getColumn(colomnIdx).getHeaderValue()  , false, false, 0, colomnIdx);
		//log.fine("header "+ colomnIdx +" width: " + hcomp.getPreferredSize());
			w = Math.max(w, hcomp.getPreferredSize().width);
		}
		for(int r = firstRow; r <= lastRow; r++)
		{
			if(r == -1){
				continue;
			}
			renderer = getCellRenderer(r, colomnIdx);
			Component comp = prepareRenderer(renderer, r, colomnIdx);
			w = Math.max(w, comp.getPreferredSize().width + 4);
			if(isCellEditable(r, colomnIdx)){
	        	TableCellEditor editor = getCellEditor(r, colomnIdx);
	        	comp = prepareEditor(editor, r, colomnIdx);
	        	w = Math.max(w, comp.getPreferredSize().width + 4);
	        }
	        
		}
		//log.fine("set preferred width: " + w);
		return w;
	}
	
	/**
	you can override it, to update table layout like execute packTable() or others.
	*/
	
	public  void tableChanged(TableModelEvent e)
	{
		//log.log(Level.INFO, "tableChanged " + e.getFirstRow() + "->" 
		//	+ e.getLastRow() + " type:" + e.getType()+ " count:"
		//	+ getRowCount());
		try{
			super.tableChanged(e);
		}catch(RuntimeException ex){
			log.log(Level.INFO, "", ex);
			//throw e;
		}
		if(enablePack){
			if(e.getType()==e.INSERT ||e.getType()==e.UPDATE)
			{
				resizeTable(e.getFirstRow(), e.getLastRow(), e.getColumn());
			}
		}
	}

	protected void resizeTable(int firstRow, int lastRow, int column)
	{
		
		//if(log.isLoggable(Level.FINE))
		//	log.fine(" row:"+ firstRow + " ~ " + lastRow + " column:" + column + " count: " + getRowCount());
		int rowCount = getRowCount() - 1;
		if(rowCount < lastRow)
			lastRow = rowCount;
		if(firstRow == TableModelEvent.HEADER_ROW){
			lastRow = getRowCount() - 1;
		}
		int firstColumn = column;
		int lastColumn = column;
		if(column == TableModelEvent.ALL_COLUMNS){
			firstColumn = 0;
			lastColumn = getColumnCount() - 1;
			if(lastColumn < 0){
				log.fine("no column");
				return;
			}
		}
		
		for(int i = firstColumn; i <= lastColumn; i++){
			int width = getPreferredColumnWidth(firstRow, lastRow, i);
			getColumnModel().getColumn(i).setPreferredWidth(width);
		}
		for (int r = firstRow; r <= lastRow; r++) {
			if(r == -1 )
				continue;
	        int h = getPreferredRowHeight(firstColumn, lastColumn, r );
	        if (getRowHeight(r) != h) {
	            setRowHeight(r, h);
	        }
	    }
	}
	
	//class FitWidthTableRenderer extends DefaultTableCellRenderer{
	//	//JCheckBox 		checkBox = new JCheckBox();
	//	
	//	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
	//					
	//		Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
	//		
	//		int oldW = table.getColumnModel().getColumn(column).getPreferredWidth();
	//		int w = comp.getPreferredSize().width;
	//		log.fine("oldW = " + oldW + " w=" + w);
	//		if(table.isCellEditable(row, column)){
	//        	TableCellEditor editor = table.getCellEditor(row, column);
	//        	Component editcomp = table.prepareEditor(editor, row, column);
	//        	if(editcomp.getPreferredSize().width > comp.getPreferredSize().width)
	//        		w = editcomp.getPreferredSize().width + 4;
	//        	
	//        }
	//        if(w > oldW){
	//        	log.fine("");
	//        	table.getColumnModel().getColumn(column).setPreferredWidth(w);
	//        }
	//        return comp;
	//	}
	//}

}
